﻿using System;

using System.Collections.Generic;
using System.Text;
using Silvermoon.Controls.Base;
using Silvermoon.Animations;
using System.Drawing;
using Silvermoon.Shapes;
using System.Diagnostics;
using Silvermoon.Windows;

namespace Silvermoon.Controls.Forms
{
    /// <summary>
    /// Abstract base class for all tooltip dialogs.
    /// </summary>
    public abstract class ToolTipBase : FormBase
    {
        #region fields

        private Window anchorWindow;
        private Control anchorControl;
        private Rectangle anchorRect;

        #endregion
        #region ctors/dtors

        public ToolTipBase()
            : base()
        {
            ControlFlags &= ~ControlFlags.CanFocus;
            Margin = Margin.Empty;
            IsHitTestVisible = false;
        }

        protected override void Dispose(bool dispose)
        {
            anchorWindow = null;
            base.Dispose(dispose);
        }

        #endregion
        #region props

        /// <summary>
        /// Gets or sets the anchor point relative to AnchorControl.
        /// </summary>
        public Rectangle AnchorBounds
        {
            get { return anchorRect; }
            set
            {
                if (anchorRect != value)
                {
                    OnAnchorBoundsChanging(value);
                    anchorRect = value;
                }
            }
        }


        /// <summary>
        /// Gets or sets the control that will hide ToolTipBase when it looses focus.
        /// </summary>
        public Control AnchorControl
        {
            get { return anchorControl; }
            set
            {
                if (anchorControl != value)
                {
                    OnAnchorControlChanging(value);
                    anchorControl = value;
                }
            }
        }

        /// <summary>
        /// Gets  whether the control can receive focus.
        /// </summary>
        /// <value></value>
        public override bool CanFocus
        {
            get { return false; }
        }

        #endregion
        #region methods

    internal protected override void OnCommand(CommandEventArgs args)
        {
            base.OnCommand(args);
            OnToolTipCommand(args);
        }

    protected virtual void OnToolTipCommand(CommandEventArgs args)
    {
        if (!args.Handled && anchorControl != null)
        {
            args.Sender = this;
            anchorControl.OnCommand(args);
        }
    }

        protected virtual void OnAnchorControlChanging(Control newControl)
        {
            if (anchorWindow != null)
            {
                anchorWindow.ViewChanged -= OnWindowScroll;
                anchorWindow = null;
            }
            Invalidate(InvalidationFlag.Internal | InvalidationFlag.Layout);

        }

        protected override void OnLocationChanged()
        {
            Invalidate(InvalidationFlag.Internal);
            base.OnInitialized();
        }

        protected override void OnLayout()
        {
            if (CheckFlag(InvalidationFlag.Internal | InvalidationFlag.Size | InvalidationFlag.Layout | InvalidationFlag.Appearance))
            {
                CalculatePosition();
            }
            base.OnLayout();
        }

        /// <summary>
        /// Calculates the location of the tooltip based on AnchorControl and AnchorPoint.
        /// </summary>
        public abstract void CalculatePosition();


        protected virtual void OnAnchorBoundsChanging(Rectangle newValue)
        {
            Invalidate(InvalidationFlag.Internal | InvalidationFlag.Layout);
        }

        protected override void OnShowing()
        {
            if (anchorControl != null)
            {
                anchorWindow = anchorControl.Window;
                if (anchorWindow != null && !anchorWindow.IsDisposed) anchorWindow.ViewChanged += OnWindowScroll;
            }
            base.OnShowing();
        }

        protected override void OnHiding()
        {
            if (anchorControl != null && anchorWindow != null)
            {
                anchorWindow.ViewChanged -= OnWindowScroll;
                anchorWindow = null;
            }
            base.OnHiding();
        }


        private void OnWindowScroll(object sender, EventArgs e)
        {
            Invalidate(InvalidationFlag.Internal);
        }

        #endregion
    }
}
